<?php
class CEmailValidator extends CValidator{
	
	public $pattern='/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/';

	public $allowEmpty=true;
	
	/**
	 * @var boolean whether to check the MX record for the email address.
	 * Defaults to false. To enable it, you need to make sure the PHP function 'checkdnsrr'
	 * exists in your PHP installation.
	 */
	public $checkMX=false;
	/**
	 * @var boolean whether to check port 25 for the email address.
	 * Defaults to false.
	 * @since 1.0.4
	 */
	public $checkPort=false;
	
	public function validateAttribute($object, $attribute, $value){		
		$value = $value[$attribute];
		if($this->allowEmpty && $this->isEmpty($value))
			return ;
		if(!$this->validateValue($value)){
			$message = $this->message !== null ? $this->message : "非合法EMAi";
			$this->addError($object, $attribute, $message);
		}		
	}
	
	public function validateValue($value){
		$valid = is_string($value) && (preg_match($this->pattern,$value));
		if($valid){
			$domain = rtrim(substr($value,strpos($value,'@')+1),'>');
		}
		if($valid&& $this->checkMX && function_exists('checkdnsrr')){
			$valid=checkdnsrr($domain,'MX');
		}
		if($valid && $this->checkPort && function_exists('fsockopen')){
			$valid=fsockopen($domain,25)!==false;
		}
		return $valid;
	}
}



/**
		 * (?:pattern) 匹配 pattern 但不获取匹配结果，也就是说这是一个非获取匹配，不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如， 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。

    (?=pattern) 正向预查，在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如，'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ，但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始。

    (?!pattern) 负向预查，在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows"，但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始
		 * Enter description here ...
		 * @var unknown_type
		 */